﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using Cotrobaie.UsersWebService;
using WebChart;
using System.Drawing.Drawing2D;
using CPreturi = Cotrobaie.UsersWebService.TipPreturi;

namespace Cotrobaie.UserControl
{
    public class Pair<U, V>
    {
        public U unu;
        public V doi;
        public Pair(U a, V b)
        {
            unu = a;
            doi = b;
        }
    }

    public struct RegressionLine
    {
        private double _a, _b;
        public double a { get { return _a; } set { _a = value; } }
        public double b { get { return _b; } set { _b = value; } }
        public RegressionLine(double a, double b)
        {
            _a = a;
            _b = b;
        }
        public RegressionLine(double[] x, double[] y)
        {
            _a = 0;
            _b = 0;
            BuildLine(x, y);
        }


        private void BuildLine(double[] x, double[] y)
        {
            int n = x.Length;
            double sx = 0, sy = 0, sxy = 0, ssqx = 0;
            for (int i = 0; i < n; i++)
            {
                sx += x[i];
                sy += y[i];
                sxy += x[i] * y[i];
                ssqx += x[i] * x[i];
            }
            double num = sx * sx - n * ssqx;
            _a = (sx * sy - n * sxy) / num;
            _b = (sx * sxy - ssqx * sy) / num;

        }

        public double f(double x)
        {
            return _a * x + _b;
        }
    }



    public partial class RezultateStatistici : System.Web.UI.UserControl
    {
        private List<Chart> rezultate = new List<Chart>();
        private List<Chart> trenduri = new List<Chart>();
        protected void Page_Load(object sender, EventArgs e)
        {
            
            iucon.web.Controls.ParameterCollection parameters = iucon.web.Controls.ParameterCollection.Instance;
            if (Server.UrlDecode(parameters["ProductID"]) == null) { Response.Write("Trebuie un ProductID"); return; }
            DateTime? dt1=null,dt2=null;
            try
            {
                if (parameters["TextBoxMinDate"] != String.Empty && parameters["TextBoxMaxDate"] != String.Empty)
                {
                    dt1 = DateTime.Parse(parameters["TextBoxMinDate"]);
                    dt2 = DateTime.Parse(parameters["TextBoxMaxDate"]);

                    if (dt1 >= dt2) dt1 = dt2 = null;
                    if (dt2 > DateTime.Now) dt2=DateTime.Now;
                }
                else if (parameters["TextBoxMinDate"] != String.Empty)
                {
                    dt1 = DateTime.Parse(parameters["TextBoxMinDate"]);
                    if (dt1 > DateTime.Now) dt1 = DateTime.Now;
                }
                else if (parameters["TextBoxMaxDate"] != String.Empty)
                {
                    dt2 = DateTime.Parse(parameters["TextBoxMaxDate"]);
                    if (dt2 > DateTime.Now) dt2 = DateTime.Now;
                }
            }
            catch { }
            /*
            if (Session["ButtonPressed"] == null && Session["CheckBoxChecked"] == null)
            {
                Session["data_start"] = dt1 ?? null;
                Session["data_end"] = dt2 ?? null;
                draw(dt1, dt2,parameters);
            }
            else
            {
                Session["ButtonPressed"] = Session["CheckBoxChecked"] = null;

                if (Session["data_start"] as DateTime? != dt1 ||
                 Session["data_end"] as DateTime? != dt2)
                {
                    
                    draw(dt1, dt2, parameters);
                }
                else
                {
                    if (parameters["Check"] == "true")
                    {
                        foreach (Chart cp in rezultate)
                            this.chartControl1.Charts.Remove(cp);
                        foreach (Chart ct in trenduri)
                            this.chartControl1.Charts.Add(ct);
                        chartControl1.RedrawChart();
                    }
                    else
                    {
                        foreach (Chart cp in trenduri)
                            this.chartControl1.Charts.Remove(cp);
                        foreach (Chart ct in rezultate)
                            this.chartControl1.Charts.Add(ct);
                        chartControl1.RedrawChart();
                    }
                }
                
            }
            */

            draw(dt1, dt2, parameters);
            System.Threading.Thread.Sleep(250);//daca e prea rapid at cerculetu e enervant :))
        }

        private void draw(DateTime? dt1, DateTime? dt2, iucon.web.Controls.ParameterCollection parameters)
        {
            using (UsersSoapClient serviciu = new UsersSoapClient("UsersSoap"))
            {
                var preturi = serviciu.GetProductPrice(long.Parse(Server.UrlDecode(parameters["ProductID"])));
                if (preturi.Success)
                {
                    var prod = preturi.Produse.ToList();

                    var Prices = from i in (from p in prod where (dt1 != null ? p.Data >= dt1 : true) && (dt2 != null ? p.Data <= dt2 : true) select p) group i by i.SiteID into h select h;
                    if (Prices.Count() != 0)
                    {
                        var regline = getRegression(Prices);
                        
                            CreateChart(Prices, regline,parameters["Check"] == "True");
                        

                    }
                    else
                    {
                        var Prices2 = from i in (from p in prod select p) group i by i.SiteID into h select h;
                        {
                            var regline = getRegression(Prices2);
                            CreateChart(Prices2, regline, parameters["Check"] == "True");
                        
                        }
                    }

                }
            }
        }

        private List<List<ChartPoint>> getRegression (System.Collections.Generic.IEnumerable<IGrouping<int, UsersWebService.TipPreturi>> Prices)
        {
            List<List<ChartPoint>> list = new List<List<ChartPoint>>();

            foreach (var grupare in Prices)
            {
                List<ChartPoint> list1 = new List<ChartPoint>();
                DateTime start, end;
                UsersWebService.TipPreturi[] listaPret;
                start = grupare.OrderBy(z => z.Data).First().Data;
                end = grupare.OrderByDescending(z => z.Data).First().Data;

                listaPret = grupare.OrderBy(z => z.Data).ToArray();

                double[] x = new double[listaPret.Length];
                double[] y = new double[listaPret.Length];
                double r = 0;
                for (int i = 0; i < listaPret.Length; i++)
                {
                    y[i] = listaPret[i].Pret ?? 0;
                    x[i] = (listaPret[i].Data - listaPret[0].Data).TotalDays;

                }
                RegressionLine line = new RegressionLine(x, y);
                for (int i = 1; i < listaPret.Length; i++)
                {
                    r += ((listaPret[i].Pret - listaPret[i - 1].Pret) / listaPret[i - 1].Pret) ?? 0;
                }
                r /= listaPret.Length - 1;

                ChartPoint p1, p2;
                p1 = new ChartPoint(start.ToString("dd.MM.yyyy"), (float)line.f(0));
                p2 = new ChartPoint(end.ToString("dd.MM.yyyy"), (float)line.f((end - start).TotalDays));

                foreach (var u in listaPret)
                {
                    list1.Add(new ChartPoint(u.Data.ToString("dd.MM.yyyy"),(float)line.f((u.Data - start).TotalDays)));
                }

                list.Add(list1);
            }

            return list;
        }
        #region old
        private string CreateChart(System.Collections.Generic.IEnumerable<IGrouping<int, UsersWebService.TipPreturi>> Prices)
        {
            chartControl1.Charts.Clear();
            //culori compatibile cu designul site-ului
            Color[] c = new Color[] { Color.Coral, Color.Black, Color.Black, Color.Green, Color.GreenYellow, Color.Gray };
            byte index = 0;

            double min = Double.MaxValue, max = Double.MinValue;
            int maxCount = 0;
            foreach (var v in Prices)
                if (v.Count() > maxCount) maxCount = v.Count();
            chartControl1.XTicksInterval = 5;
            chartControl1.YValuesInterval = 5;
            chartControl1.XValuesInterval = (maxCount + 1) / 2; //afisez primu si ultimu

            foreach (var p in Prices.Reverse())
            {
                LineChart chart = new LineChart();

                chart.Line.Width = 3F;
                chart.Line.LineJoin = LineJoin.Round;
                chart.Line.Color = c[index];
                chart.Fill.Color = c[index];
                chart.LineMarker = new DiamondLineMarker(3, c[index], c[index++]);
                chart.Shadow.Visible = false;
                chart.DataXValueField = "Data";
                if (index == c.Count()) index = 0;//daca vom avea mai multi produceri

                var pret = p.OrderBy(x => x.Data);
                chart.Legend = pret.First().SiteName;
                if (pret.Min(x => x.Pret).Value < min) min = pret.Min(x => x.Pret).Value;
                if (pret.Max(x => x.Pret).Value > max) max = pret.Max(x => x.Pret).Value;

                int count = 0;
                foreach (var pr in pret)
                { chart.Data.Add(new ChartPoint(pr.Data.ToString("dd.MM.yyyy"), (float)pr.Pret)); count++; }
                while (count < maxCount)
                { chart.Data.Add(new ChartPoint(pret.Last().Data.ToString("dd.MM.yyyy"), (float)pret.Last().Pret)); count++; }
                //chart.Data.Add(new ChartPoint(DateTime.Now.ToString("dd.MM.yyyy"), (float)pret.Last().Pret)); count++;

                chartControl1.Charts.Add(chart);
            }
            chartControl1.YCustomStart = (float)min - 1;
            chartControl1.YCustomEnd = (float)max + 1;
            chartControl1.RedrawChart();
            return chartControl1.FileName;
        }
        #endregion
        private string CreateChart(System.Collections.Generic.IEnumerable<IGrouping<int, UsersWebService.TipPreturi>> Prices, List<List<ChartPoint>> reglines, bool check)
        {
            
            rezultate.Clear();
            trenduri.Clear();
            chartControl1.Charts.Clear();
            //culori compatibile cu designul site-ului
            Color[] c = new Color[] { Color.Coral, Color.Black, Color.Coral, Color.Black, Color.GreenYellow, Color.Gray };
            byte index = 0;

            double min = Double.MaxValue, max = Double.MinValue;
            int maxCount = 0;
            foreach (var v in Prices)
                if (v.Count() > maxCount) maxCount = v.Count();
            chartControl1.XTicksInterval = 5;
            chartControl1.YValuesInterval = 5;
            chartControl1.XValuesInterval = (maxCount + 1) / 2; //afisez primu si ultimu

            bool b=false;
            foreach (var p in Prices.Reverse())
            {
                LineChart chart = new LineChart();

                chart.Line.Width = 3F;
                chart.Line.LineJoin = LineJoin.Round;
                chart.Line.Color = c[index];
                chart.Fill.Color = c[index];
                chart.LineMarker = new DiamondLineMarker(3, c[index], c[index++]);
                chart.Shadow.Visible = false;
                chart.DataXValueField = "Data";
                if (index == c.Count()) index = 0;//daca vom avea mai multi produceri

                var pret = p.OrderBy(x => x.Data);
                if (!b) { chart.Legend = "Ebay"; b = true; } else chart.Legend = "Amazon";//doar pt cazu asta cu 2
                if (pret.Min(x => x.Pret).Value < min) min = pret.Min(x => x.Pret).Value;
                if (pret.Max(x => x.Pret).Value > max) max = pret.Max(x => x.Pret).Value;

                int count = 0;
                foreach (var pr in pret)
                { chart.Data.Add(new ChartPoint(pr.Data.ToString("dd.MM.yyyy"), (float)pr.Pret)); count++; }
                while (count < maxCount)
                { chart.Data.Add(new ChartPoint(pret.Last().Data.ToString("dd.MM.yyyy"), (float)pret.Last().Pret)); count++; }
                //chart.Data.Add(new ChartPoint(DateTime.Now.ToString("dd.MM.yyyy"), (float)pret.Last().Pret)); count++;
                rezultate.Add(chart);
                if(!check)
                    chartControl1.Charts.Add(chart);
            }
            int i = 0;
            if (check)
            foreach (var p in reglines.Reverse<List<ChartPoint>>().ToList())
            {
                LineChart chart = new LineChart();

                chart.Line.Width = 3F;
                chart.Line.LineJoin = LineJoin.Round;
                chart.Line.Color = c[index];
                chart.Fill.Color = c[index];
                chart.Shadow.Visible = false;
                chart.LineMarker = new DiamondLineMarker(3, c[index], c[index++]);
                chart.Legend = rezultate[i].Legend;
                chart.DataXValueField = "Data";
                if (index == c.Count()) index = 0;//daca vom avea mai multi produceri

                //chart.Data.Add(p.unu);
                //chart.Data.Add(p.doi);
                try { if (p.Min(x => x.YValue) < min) min = p.Min(x => x.YValue); }
                catch { }
                try { if (p.Max(x => x.YValue) > max) max = p.Max(x => x.YValue); }
                catch { }

                int count = 0;
                foreach (var u in p)
                { chart.Data.Add(u); count++; }
                while (count < maxCount)
                { chart.Data.Add(new ChartPoint(DateTime.Parse(p.Last().XValue).ToString("dd.MM.yyyy"), (float)p.Last().YValue)); count++; }

                chartControl1.Charts.Add(chart);
                trenduri.Add(chart);
                i++;
            }

            if (max == min) chartControl1.YValuesInterval = 1;
            else if (max - min < 10) chartControl1.YValuesInterval = (int)((max - min) / 1.2);
            else if (max - min > 30) chartControl1.YValuesInterval = (int)((max - min) / 3);
            chartControl1.YCustomStart = (float)min - 1;
            chartControl1.YCustomEnd = (float)max + 1;
            chartControl1.RedrawChart();
            return chartControl1.FileName;
        }

    }
}